package network

import (
	"context"
	"fmt"
	"google.golang.org/grpc"
	"log"
	"net"
	"sync"
)

var (
	receiverID string
	wg         sync.WaitGroup
	msgHandler func([]byte) // Handler for received messages
)

type server struct {
	UnimplementedSendServer
}

type UnimplementedSendServer struct{}

func (s *server) RBCSendByteMsg(ctx context.Context, in *RawMessage) (*Empty, error) {
	go msgHandler(in.Msg)
	return &Empty{}, nil
}

func (s *server) ABASendByteMsg(ctx context.Context, in *RawMessage) (*Empty, error) {
	go msgHandler(in.Msg)
	return &Empty{}, nil
}

func (s *server) PRFSendByteMsg(ctx context.Context, in *RawMessage) (*Empty, error) {
	go msgHandler(in.Msg)
	return &Empty{}, nil
}

func (s *server) ECRBCSendByteMsg(ctx context.Context, in *RawMessage) (*Empty, error) {
	go msgHandler(in.Msg)
	return &Empty{}, nil
}

func (s *server) CBCSendByteMsg(ctx context.Context, in *RawMessage) (*Empty, error) {
	go msgHandler(in.Msg)
	return &Empty{}, nil
}

func (s *server) EVCBCSendByteMsg(ctx context.Context, in *RawMessage) (*Empty, error) {
	go msgHandler(in.Msg)
	return &Empty{}, nil
}

func (s *server) MVBASendByteMsg(ctx context.Context, in *RawMessage) (*Empty, error) {
	go msgHandler(in.Msg)
	return &Empty{}, nil
}

func (s *server) RetrieveSendByteMsg(ctx context.Context, in *RawMessage) (*Empty, error) {
	go msgHandler(in.Msg)
	return &Empty{}, nil
}

func (s *server) CBRSendByteMsg(ctx context.Context, in *RawMessage) (*Empty, error) {
	go msgHandler(in.Msg)
	return &Empty{}, nil
}

func (s *server) SendMsg(ctx context.Context, in *RawMessage) (*Empty, error) {
	return &Empty{}, nil
}

func (s *server) SendRequest(ctx context.Context, in *Request) (*RawMessage, error) {
	return &RawMessage{Msg: []byte("rep")}, nil
}

func (s *server) Join(ctx context.Context, in *RawMessage) (*RawMessage, error) {
	reply := []byte("hi")
	return &RawMessage{Msg: reply, Result: true}, nil
}

type SendServer interface {
	RBCSendByteMsg(context.Context, *RawMessage) (*Empty, error)
	ABASendByteMsg(context.Context, *RawMessage) (*Empty, error)
	PRFSendByteMsg(context.Context, *RawMessage) (*Empty, error)
	ECRBCSendByteMsg(context.Context, *RawMessage) (*Empty, error)
	CBCSendByteMsg(context.Context, *RawMessage) (*Empty, error)
	EVCBCSendByteMsg(context.Context, *RawMessage) (*Empty, error)
	MVBASendByteMsg(context.Context, *RawMessage) (*Empty, error)
	RetrieveSendByteMsg(context.Context, *RawMessage) (*Empty, error)
	CBRSendByteMsg(context.Context, *RawMessage) (*Empty, error)
	SendMsg(context.Context, *RawMessage) (*Empty, error)
	SendRequest(context.Context, *Request) (*RawMessage, error)
	Join(context.Context, *RawMessage) (*RawMessage, error)
}

func register(port string) {
	lis, err := net.Listen("tcp", port)
	if err != nil {
		log.Printf("[Communication Receiver Error] failed to listen %v", err)
		return
	}

	log.Printf("[Communication Receiver] listening to port %v", port)
	serveGRPC(lis)
}

func serveGRPC(lis net.Listener) {
	defer wg.Done()

	s := grpc.NewServer(grpc.MaxRecvMsgSize(52428800), grpc.MaxSendMsgSize(52428800))
	// Register the server - in a real implementation this would be generated from proto
	// For now, we use a manual implementation
	RegisterSendServer(s, &server{})

	if err := s.Serve(lis); err != nil {
		log.Printf("[Communication Receiver Error] failed to serve: %v", err)
	}
}

// RegisterSendServer registers the gRPC server implementation
// This would normally be generated from proto file, but we implement it manually
func RegisterSendServer(s *grpc.Server, srv SendServer) {
	// Manual registration using reflection
	// We register the service manually since we don't have generated code
	serviceDesc := &grpc.ServiceDesc{
		ServiceName: "communication.Send",
		HandlerType: (*SendServer)(nil),
		Methods: []grpc.MethodDesc{
			{
				MethodName: "RBCSendByteMsg",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(RawMessage)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).RBCSendByteMsg(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/RBCSendByteMsg",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).RBCSendByteMsg(ctx, req.(*RawMessage))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
			{
				MethodName: "ABASendByteMsg",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(RawMessage)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).ABASendByteMsg(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/ABASendByteMsg",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).ABASendByteMsg(ctx, req.(*RawMessage))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
			{
				MethodName: "PRFSendByteMsg",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(RawMessage)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).PRFSendByteMsg(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/PRFSendByteMsg",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).PRFSendByteMsg(ctx, req.(*RawMessage))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
			{
				MethodName: "ECRBCSendByteMsg",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(RawMessage)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).ECRBCSendByteMsg(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/ECRBCSendByteMsg",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).ECRBCSendByteMsg(ctx, req.(*RawMessage))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
			{
				MethodName: "CBCSendByteMsg",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(RawMessage)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).CBCSendByteMsg(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/CBCSendByteMsg",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).CBCSendByteMsg(ctx, req.(*RawMessage))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
			{
				MethodName: "EVCBCSendByteMsg",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(RawMessage)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).EVCBCSendByteMsg(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/EVCBCSendByteMsg",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).EVCBCSendByteMsg(ctx, req.(*RawMessage))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
			{
				MethodName: "MVBASendByteMsg",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(RawMessage)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).MVBASendByteMsg(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/MVBASendByteMsg",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).MVBASendByteMsg(ctx, req.(*RawMessage))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
			{
				MethodName: "RetrieveSendByteMsg",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(RawMessage)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).RetrieveSendByteMsg(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/RetrieveSendByteMsg",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).RetrieveSendByteMsg(ctx, req.(*RawMessage))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
			{
				MethodName: "CBRSendByteMsg",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(RawMessage)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).CBRSendByteMsg(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/CBRSendByteMsg",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).CBRSendByteMsg(ctx, req.(*RawMessage))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
			{
				MethodName: "SendMsg",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(RawMessage)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).SendMsg(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/SendMsg",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).SendMsg(ctx, req.(*RawMessage))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
			{
				MethodName: "SendRequest",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(Request)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).SendRequest(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/SendRequest",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).SendRequest(ctx, req.(*Request))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
			{
				MethodName: "Join",
				Handler: func(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
					in := new(RawMessage)
					if err := dec(in); err != nil {
						return nil, err
					}
					if interceptor == nil {
						return srv.(SendServer).Join(ctx, in)
					}
					info := &grpc.UnaryServerInfo{
						Server:     srv,
						FullMethod: "/communication.Send/Join",
					}
					handler := func(ctx context.Context, req interface{}) (interface{}, error) {
						return srv.(SendServer).Join(ctx, req.(*RawMessage))
					}
					return interceptor(ctx, in, info, handler)
				},
			},
		},
		Streams:  []grpc.StreamDesc{},
		Metadata: "communication.proto",
	}
	s.RegisterService(serviceDesc, srv)
}

func StartReceiver(rid string, port string, handler func([]byte)) {
	receiverID = rid
	msgHandler = handler

	wg.Add(1)
	go register(port)
	wg.Wait()
}

// RegisterSendServer is now implemented above in serveGRPC

// Dummy implementation - in real code this would be generated from proto
func (s *UnimplementedSendServer) RBCSendByteMsg(context.Context, *RawMessage) (*Empty, error) {
	return nil, fmt.Errorf("not implemented")
}

func (s *UnimplementedSendServer) ABASendByteMsg(context.Context, *RawMessage) (*Empty, error) {
	return nil, fmt.Errorf("not implemented")
}

func (s *UnimplementedSendServer) PRFSendByteMsg(context.Context, *RawMessage) (*Empty, error) {
	return nil, fmt.Errorf("not implemented")
}

func (s *UnimplementedSendServer) ECRBCSendByteMsg(context.Context, *RawMessage) (*Empty, error) {
	return nil, fmt.Errorf("not implemented")
}

func (s *UnimplementedSendServer) CBCSendByteMsg(context.Context, *RawMessage) (*Empty, error) {
	return nil, fmt.Errorf("not implemented")
}

func (s *UnimplementedSendServer) EVCBCSendByteMsg(context.Context, *RawMessage) (*Empty, error) {
	return nil, fmt.Errorf("not implemented")
}

func (s *UnimplementedSendServer) MVBASendByteMsg(context.Context, *RawMessage) (*Empty, error) {
	return nil, fmt.Errorf("not implemented")
}

func (s *UnimplementedSendServer) RetrieveSendByteMsg(context.Context, *RawMessage) (*Empty, error) {
	return nil, fmt.Errorf("not implemented")
}

func (s *UnimplementedSendServer) CBRSendByteMsg(context.Context, *RawMessage) (*Empty, error) {
	return nil, fmt.Errorf("not implemented")
}

func (s *UnimplementedSendServer) SendMsg(context.Context, *RawMessage) (*Empty, error) {
	return nil, fmt.Errorf("not implemented")
}

func (s *UnimplementedSendServer) SendRequest(context.Context, *Request) (*RawMessage, error) {
	return nil, fmt.Errorf("not implemented")
}

func (s *UnimplementedSendServer) Join(context.Context, *RawMessage) (*RawMessage, error) {
	return nil, fmt.Errorf("not implemented")
}

